class Base {
    int a;
    int b;
    int c;
    {
        System.out.println("Base中的构造代码块");
    }
    static {
        System.out.println("Base中的静态代码块");
    }

    public Base() {
        //不带参数的构造方法编译器会默认提供
        //你自己写了就不会提供了
        System.out.println("Base中不带参数的构造方法");
    }

    public Base(int a, int b, int c) {
        this.a = a;
        this.b = b;
        this.c = c;
        System.out.println("Base中3个参数的构造方法");
    }

    public void methodA(){
        System.out.println("Base中的methodA()");
    }

    public void methodB(){
        System.out.println("Base中的methodB()");
    }
}

class Derived extends Base{
    int a; // 与父类中成员a同名，且类型相同
    char b; // 与父类中成员b同名，但类型不同

    {
        System.out.println("Derived中的构造代码块");
    }

    static {
        System.out.println("Derived中的静态代码块");
    }

    public Derived() {
        //super();// 注意子类构造方法中默认会调用基类的无参构造方法：super(),
        //没有写时,编译器会自动添加，而且super()必须是子类构造方法中第一条语句，
        //super() 与 this() 冲突，都要在第一条语句。
        //并且只能出现一次
        System.out.println("Derived中不带参数的构造方法");
    }

    public Derived(int a,int b,int c,int d, char e) {
        super(a,b,c);
        this.a = d;
        this.b = e;
        System.out.println("Derived中5个参数的构造方法");
    }


    //与父类methodA()构成重载
    public void methodA(int a) {
        System.out.println("Derived中的method(int)");
    }

    //与父类methodB()构成重写
    public void methodB() {
        System.out.println("Derived中的methodB()");
    }

    public void method1(){
        a = 100; // 访问的是子类自己新增的a
        b = 101; // 访问的是子类自己新增的b
        c = 102; // 子类没有c，访问的肯定是从父类继承下来的c
        //d = 103; // 编译失败，因为父类和子类都没有定义成员变量b

        //成员变量访问遵循就近原则，自己有优先自己的，如果没有则向父类中找。
    }

    public void method2(){
        methodA(); // 没有传参，访问父类中的methodA()
        methodA(20); // 传递int参数，访问子类中的methodA(int)
        methodB(); // 直接访问，则永远访问到的都是子类中的methodB()，基类的无法访问到
    }

    public void method3(){
        // 对于同名的成员变量，直接访问时，访问的都是子类的
        a = 100; // 等价于： this.a = 100;
        b = 101; // 等价于： this.b = 101;
        // 注意：this是当前对象的引用
        // 访问父类的成员变量时，需要借助super关键字

        // super是获取到子类对象中从基类继承下来的部分
        super.a = 200;
        super.b = 201;
        //这里访问的是父类的a，b

        // 父类和子类中构成重载的方法，直接可以通过参数列表区分清访问父类还是子类方法
        methodA(); // 没有传参，访问父类中的methodA()
        methodA(20); // 传递int参数，访问子类中的methodA(int)

        // 如果在子类中要访问重写的基类方法，则需要借助super关键字
        methodB(); // 直接访问，则永远访问到的都是子类中的methodA()，基类的无法访问到
        super.methodB(); // 访问基类的methodB()
    }

    public static void test() {
        //super与this一样只能在非静态方法中使用
        //super.methodB();//编译报错
    }
}
public class Test2 {
    public static void main(String[] args) {
        //父类与子类的构造方法
        //子类对象构造时，需要先调用基类构造方法，然后执行子类的构造方法。
        //super 调用父类的构造方法
        Derived derived1 = new Derived();

        //先执行父类与子类的静态代码块，在类的加载阶段，只执行一次
        //然后执行父类的构造代码块和构造方法
        //最后执行子类的构造代码块和构造方法

        System.out.println("==============");

        Derived derived2 = new Derived(1,2,3,4,'5');
    }

    public static void main2(String[] args) {
        //super关键字访问父类的成员
        Derived derived = new Derived();
        derived.method3();
    }

    public static void main1(String[] args) {
        Derived derived = new Derived();
        derived.method2();
    }
}
